﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;

namespace CodeExample.Classes
{
    public class Linq
    {
        public string QueryOverStrings()
        {

            #region variables
            List<Car> myCars = new List<Car>() {
            new Car{ PetName = "Henry", Color = "Silver", Speed = 100, Make = "BMW"},
            new Car{ PetName = "Daisy", Color = "Tan", Speed = 90, Make = "BMW"},
            new Car{ PetName = "Mary", Color = "Black", Speed = 55, Make = "VW"},
            new Car{ PetName = "Clunker", Color = "Rust", Speed = 5, Make = "Yugo"},
            new Car{ PetName = "Melvin", Color = "White", Speed = 43, Make = "Ford"}
            };

            ProductInfo[] itemsInStock = new[] {
            new ProductInfo{ Name = "Mac's Coffee",
            Description = "Coffee with TEETH",
            NumberInStock = 24},
            new ProductInfo{ Name = "Milk Maid Milk",
            Description = "Milk cow's love",
            NumberInStock = 100},
            new ProductInfo{ Name = "Pure Silk Tofu",
            Description = "Bland as Possible",
            NumberInStock = 120},
            new ProductInfo{ Name = "Cruchy Pops",
            Description = "Cheezy, peppery goodness",
            NumberInStock = 2},
            new ProductInfo{ Name = "RipOff Water",
            Description = "From the tap to your wallet",
            NumberInStock = 100},
            new ProductInfo{ Name = "Classic Valpo Pizza",
            Description = "Everyone loves pizza!",
            NumberInStock = 73}
            };
            #endregion

            // Assume we have an array of strings.
            string[] currentVideoGames = { "Morrowind", "Uncharted 2", "Fallout 3", "Daxter", "System Shock 2" };
            // Build a query expression to find the items in the array
            // that have an embedded space.
            IEnumerable<string> subset = from g in currentVideoGames
                                         where g.Contains(" ")
                                         orderby g
                                         select g;


            int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
            // Only print items less than 10.
            IEnumerable<int> subset2 = from i in numbers where i < 10 select i;
            System.Collections.IEnumerable subset3 = from i in numbers where i < 10 select i;
            var subset4 = from i in numbers where i < 10 select i;


            Console.WriteLine("***** LINQ Transformations *****\n");
            IEnumerable<string> subset5 = GetStringSubset();

            String[] asdf = GetStringSubsetAsArray();


            LINQOverArrayList();

            OfTypeAsFilter();

            GetFastCars(myCars);

            SelectEverything(itemsInStock);
            GetOverstock(itemsInStock);
            GetNamesAndDescriptions(itemsInStock);
            Array objs = GetProjectedSubset();
            ReverseEverything(itemsInStock);
            AlphabetizeProductNames(itemsInStock);

            return "";
        }

        static void QueryOverInts()
        {
            int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
            // Get numbers less than ten.
            var subset = from i in numbers where i < 10 select i;
            // LINQ statement evaluated here!
            foreach (var i in subset)
                Console.WriteLine("{0} < 10", i);
            Console.WriteLine();
            // Change some data in the array.
            numbers[0] = 4;
            // Evaluated again!
            foreach (var j in subset)
                Console.WriteLine("{0} < 10", j);
            Console.WriteLine();
        }

        static void ImmediateExecution()
        {
            int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
            // Get data RIGHT NOW as int[].
            int[] subsetAsIntArray =
            (from i in numbers where i < 10 select i).ToArray<int>();
            // Get data RIGHT NOW as List<int>.
            List<int> subsetAsListOfInts =
            (from i in numbers where i < 10 select i).ToList<int>();
        }

        static IEnumerable<string> GetStringSubset()
        {
            string[] colors = { "Light Red", "Green", "Yellow", "Dark Red", "Red", "Purple" };
            // Note subset is an IEnumerable<string> compatible object.
            IEnumerable<string> theRedColors = from c in colors
                                               where c.Contains("Red")
                                               select c;
            return theRedColors;
        }

        static string[] GetStringSubsetAsArray()
        {
            string[] colors = { "Light Red", "Green", "Yellow", "Dark Red", "Red", "Purple" };
            var theRedColors = from c in colors
                               where c.Contains("Red")
                               select c;
            // Map results into an array.
            return theRedColors.ToArray();
        }

        static void GetFastCars(List<Car> myCars)
        {
            // Find all Car objects in the List<>, where the Speed is
            // greater than 55.
            var fastCars = from c in myCars where c.Speed > 55 select c;
            foreach (var car in fastCars)
            {
                Console.WriteLine("{0} is going too fast!", car.PetName);
            }

            var fastCars2 = from c in myCars where c.Speed > 90 && c.Make == "BMW" select c;
            foreach (var car in fastCars2)
            {
                Console.WriteLine("{0} is going too fast!", car.PetName);
            }
        }

        static void LINQOverArrayList()
        {
            Console.WriteLine("***** LINQ over ArrayList *****");
            // Here is a nongeneric collection of cars.
            ArrayList myCars = new ArrayList() {
            new Car{ PetName = "Henry", Color = "Silver", Speed = 100, Make = "BMW"},
            new Car{ PetName = "Daisy", Color = "Tan", Speed = 90, Make = "BMW"},
            new Car{ PetName = "Mary", Color = "Black", Speed = 55, Make = "VW"},
            new Car{ PetName = "Clunker", Color = "Rust", Speed = 5, Make = "Yugo"},
            new Car{ PetName = "Melvin", Color = "White", Speed = 43, Make = "Ford"}
            };
            // Transform ArrayList into an IEnumerable<T>-compatible type.
            var myCarsEnum = myCars.OfType<Car>();
            // Create a query expression targeting the compatible type.
            var fastCars = from c in myCarsEnum where c.Speed > 55 select c;
            foreach (var car in fastCars)
            {
                Console.WriteLine("{0} is going too fast!", car.PetName);
            }
        }

        static void OfTypeAsFilter()
        {
            // Extract the ints from the ArrayList.
            ArrayList myStuff = new ArrayList();
            myStuff.AddRange(new object[] { 10, 400, 8, false, new Car(), "string data" });
            var myInts = myStuff.OfType<int>();
            // Prints out 10, 400, and 8.
            foreach (int i in myInts)
            {
                Console.WriteLine("Int value: {0}", i);
            }
        }

        static void SelectEverything(ProductInfo[] products)
        {
            // Get everything!
            Console.WriteLine("All product details:");
            var allProducts = from p in products select p;
        }

        static void GetOverstock(ProductInfo[] products)
        {
            Console.WriteLine("The overstock items!");
            // Get only the items where we have more than
            // 25 in stock.
            var overstock = from p in products where p.NumberInStock > 25 select p;

        }

        static void GetNamesAndDescriptions(ProductInfo[] products)
        {
            Console.WriteLine("Names and Descriptions:");
            var nameDesc = from p in products select new { p.Name, p.Description };
        }

        static Array GetProjectedSubset()
        {
            ProductInfo[] products = new[] {
            new ProductInfo{ Name = "Mac's Coffee",
            Description = "Coffee with TEETH",
            NumberInStock = 24},
            new ProductInfo{ Name = "Milk Maid Milk",
            Description = "Milk cow's love",
            NumberInStock = 100},
            new ProductInfo{ Name = "Pure Silk Tofu",
            Description = "Bland as Possible",
            NumberInStock = 120},
            new ProductInfo{ Name = "Cruchy Pops",
            Description = "Cheezy, peppery goodness",
            NumberInStock = 2},
            new ProductInfo{ Name = "RipOff Water",
            Description = "From the tap to your wallet",
            NumberInStock = 100},
            new ProductInfo{ Name = "Classic Valpo Pizza",
            Description = "Everyone loves pizza!",
            NumberInStock = 73}
            };
            var nameDesc = from p in products select new { p.Name, p.Description };
            return nameDesc.ToArray(); 
        }

        static void GetCountFromQuery()
        {
            string[] currentVideoGames = {"Morrowind", "Uncharted 2","Fallout 3", "Daxter", "System Shock 2"};
            // Get count from the query.
            int numb = (from g in currentVideoGames where g.Length > 6 select g).Count<string>();
        }

        static void ReverseEverything(ProductInfo[] products)
        {
            Console.WriteLine("Product in reverse:");
            var allProducts = from p in products select p;
            foreach (var prod in allProducts.Reverse())
            {
                Console.WriteLine(prod.ToString());
            }
        }

        static void AlphabetizeProductNames(ProductInfo[] products)
        {
            // Get names of products, alphabetized.
            var subset = from p in products orderby p.Name ascending select p;
            Console.WriteLine("Ordered by Name:");
        }

        static void DisplayDiff()
        {
            List<string> myCars = new List<String> { "Yugo", "Aztec", "BMW" };
            List<string> yourCars = new List<String> { "BMW", "Saab", "Aztec" };
            var carDiff = (from c in myCars select c)
            .Except(from c2 in yourCars select c2);
            Console.WriteLine("Here is what you don't have, but I do:");
            foreach (string s in carDiff)
                Console.WriteLine(s); // Prints Yugo.
        }
    }

    class Car
    {
        public string PetName { get; set; }
        public string Color { get; set; }
        public int Speed { get; set; }
        public string Make { get; set; }
    }

    class ProductInfo
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public int NumberInStock { get; set; }
        public override string ToString()
        {
            return string.Format("Name={0}, Description={1}, Number in Stock={2}",
            Name, Description, NumberInStock);
        }
    }


}